package com.xnxkj.wx.micro.mch.bean.message.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.xnxkj.wx.micro.mch.bean.message.response.MediaUploadResultMessage;
import com.xnxkj.wx.micro.mch.utils.EncryptUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.security.cert.CertificateException;
import javax.security.cert.X509Certificate;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 申请入驻的消息体
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class SubmitMessage extends RequestMessage {
    /**
     * 版本号
     * 固定为3.0
     */
    private String version;

    /**
     * 平台证书序列号
     */
    @JsonProperty("cert_sn")
    private String certSn;

    /**
     * 商户号
     */
    @JsonProperty("mch_id")
    private String mchId;

    /**
     * 业务申请编号
     */
    @JsonProperty("business_code")
    private String businessCode;

    /**
     * 身份证人像面照片
     */
    @JsonProperty("id_card_copy")
    private String idCardCopy;

    /**
     * 身份证国徽面照片
     */
    @JsonProperty("id_card_national")
    private String idCardNational;

    /**
     * 身份证姓名
     */
    @JsonProperty("id_card_name")
    private String idCardName;

    /**
     * 身份证号码
     */
    @JsonProperty("id_card_number")
    private String idCardNumber;

    /**
     * 身份证有效期限
     */
    @JsonProperty("id_card_valid_time")
    private String idCardValidTime;

    /**
     * 开户名称
     */
    @JsonProperty("account_name")
    private String accountName;

    /**
     * 开户行
     */
    @JsonProperty("account_bank")
    private String accountBank;

    /**
     * 开户行省市编码
     */
    @JsonProperty("bank_address_code")
    private String bankAddressCode;

    /**
     * 开户行名称（含支行）
     */
    @JsonProperty("bank_name")
    private String bankName;

    /**
     * 银行账号
     */
    @JsonProperty("account_number")
    private String accountNumber;

    /**
     * 门店名称
     */
    @JsonProperty("store_name")
    private String storeName;

    /**
     * 门店城市编码
     */
    @JsonProperty("store_address_code")
    private String storeAddressCode;

    /**
     * 门店街道名称
     */
    @JsonProperty("store_street")
    private String storeStreet;

    /**
     * 门店经度
     */
    @JsonProperty("store_longitude")
    private String storeLongitude;

    /**
     * 门店纬度
     */
    @JsonProperty("store_latitude")
    private String storeLatitude;

    /**
     * 门店门口照片
     */
    @JsonProperty("store_entrance_pic")
    private String storeEntrancePic;

    /**
     * 店内环境照片
     */
    @JsonProperty("indoor_pic")
    private String indoorPic;

    /**
     * 经营场地证明
     */
    @JsonProperty("address_certification")
    private String addressCertification;

    /**
     * 商户简称
     */
    @JsonProperty("merchant_shortname")
    private String merchantShortName;

    /**
     * 客服电话
     */
    @JsonProperty("service_phone")
    private String servicePhone;

    /**
     * 服务描述
     */
    @JsonProperty("product_desc")
    private String productDesc;

    /**
     * 费率
     */
    private String rate;

    /**
     * 补充说明
     */
    @JsonProperty("business_addition_desc")
    private String businessAdditionDesc;

    /**
     * 补充材料
     */
    @JsonProperty("business_addition_pics")
    private String businessAdditionPics;

    /**
     * 联系人姓名
     */
    private String contact;

    /**
     * 联系人手机号
     */
    @JsonProperty("contact_phone")
    private String contactPhone;

    /**
     * 联系人邮箱
     */
    @JsonProperty("contact_email")
    private String contactEmail;

    public static class Builder{
        /**
         * 平台加密证书
         */
        private X509Certificate x509Certificate;
        private SubmitMessage message;

        public Builder(byte[] certificateContent, String certSn) throws CertificateException {
            this(X509Certificate.getInstance(certificateContent), certSn);
        }

        @SuppressWarnings("WeakerAccess")
        public Builder(X509Certificate certificate, String certSn) {
            this.x509Certificate = certificate;
            message = new SubmitMessage();
            message.setVersion("3.0");
            message.setCertSn(certSn);
        }

        public Builder mchId(String mchId){
            message.setMchId(mchId);
            return this;
        }

        public Builder businessCode(String businessCode){
            message.setBusinessCode(businessCode);
            return this;
        }

        public Builder idCardCopy(MediaUploadResultMessage mediaUploadResultMessage){
            message.setIdCardCopy(mediaUploadResultMessage.getMediaId());
            return this;
        }

        public Builder idCardCopy(String idCardCopyMediaId){
            message.setIdCardCopy(idCardCopyMediaId);
            return this;
        }

        public Builder idCardNational(MediaUploadResultMessage mediaUploadResultMessage){
            message.setIdCardNational(mediaUploadResultMessage.getMediaId());
            return this;
        }

        public Builder idCardNational(String idCareNationalMediaId){
            message.setIdCardNational(idCareNationalMediaId);
            return this;
        }

        public Builder idCardName(String idCardName) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
            message.setIdCardName(EncryptUtils.rsaEncrypt(x509Certificate, idCardName));
            return this;
        }

        public Builder idCardNumber(String idCardNumber) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
            message.setIdCardNumber(EncryptUtils.rsaEncrypt(x509Certificate, idCardNumber));
            return this;
        }

        public Builder idCardValidTime(String startDate, String duration){
            message.setIdCardValidTime(String.format("[\"%s\",\"%s\"]", startDate, duration));
            return this;
        }

        public Builder idCardValidTime(String idCardValidTime){
            message.setIdCardValidTime(idCardValidTime);
            return this;
        }

        public Builder accountName(String accountName) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
            message.setAccountName(EncryptUtils.rsaEncrypt(x509Certificate, accountName));
            return this;
        }

        public Builder accountBank(String accountBank){
            message.setAccountBank(accountBank);
            return this;
        }

        public Builder bankAddressCode(String bankAddressCode){
            message.setBankAddressCode(bankAddressCode);
            return this;
        }

        public Builder bankName(String bankName){
            message.setBankName(bankName);
            return this;
        }

        public Builder accountNumber(String accountNumber) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
            message.setAccountNumber(EncryptUtils.rsaEncrypt(x509Certificate, accountNumber));
            return this;
        }

        public Builder storeName(String storeName){
            message.setStoreName(storeName);
            return this;
        }

        public Builder storeAddressCode(String storeAddressCode){
            message.setStoreAddressCode(storeAddressCode);
            return this;
        }

        public Builder storeStreet(String storeStreet){
            message.setStoreStreet(storeStreet);
            return this;
        }

        public Builder storeLongitude(String storeLongitude){
            message.setStoreLongitude(storeLongitude);
            return this;
        }

        public Builder storeLatitude(String storeLatitude){
            message.setStoreLatitude(storeLatitude);
            return this;
        }

        public Builder storeEntrancePic(MediaUploadResultMessage uploadMessage){
            message.setStoreEntrancePic(uploadMessage.getMediaId());
            return this;
        }

        public Builder storeEntrancePic(String storeEntrancePicMediaId){
            message.setStoreEntrancePic(storeEntrancePicMediaId);
            return this;
        }

        public Builder indoorPic(MediaUploadResultMessage mediaUploadResultMessage){
            message.setIndoorPic(mediaUploadResultMessage.getMediaId());
            return this;
        }

        public Builder indoorPic(String indoorPicMediaId){
            message.setIndoorPic(indoorPicMediaId);
            return this;
        }

        public Builder addressCertification(MediaUploadResultMessage mediaUploadResultMessage){
            message.setAddressCertification(mediaUploadResultMessage.getMediaId());
            return this;
        }

        public Builder addressCertification(String addressCertificationMediaId){
            message.setAddressCertification(addressCertificationMediaId);
            return this;
        }

        public Builder merchantShortName(String merchantShortName){
            message.setMerchantShortName(merchantShortName);
            return this;
        }

        public Builder servicePhone(String servicePhone){
            message.setServicePhone(servicePhone);
            return this;
        }

        public Builder productDesc(String productDesc){
            message.setProductDesc(productDesc);
            return this;
        }

        public Builder rate(String rate){
            message.setRate(rate);
            return this;
        }

        public Builder businessAdditionDesc(String businessAdditionDesc){
            message.setBusinessAdditionDesc(businessAdditionDesc);
            return this;
        }

        public Builder businessAdditionPics(List<MediaUploadResultMessage> mediaUploadResultMessages){
            message.setBusinessAdditionPics(
                    mediaUploadResultMessages.stream()
                            .map(MediaUploadResultMessage::getMediaId)
                            .collect(Collectors.joining("\",\"", "[\"", "\"]"))
            );
            return this;
        }

        public Builder contact(String contact) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
            message.setContact(EncryptUtils.rsaEncrypt(x509Certificate, contact));
            return this;
        }

        public Builder contactPhone(String contactPhone) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
            message.setContactPhone(EncryptUtils.rsaEncrypt(x509Certificate, contactPhone));
            return this;
        }

        public Builder contactEmail(String contactEmail) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
            message.setContactPhone(EncryptUtils.rsaEncrypt(x509Certificate, contactEmail));
            return this;
        }

        public SubmitMessage build(){
            return message;
        }
    }
}
